package data.generators;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathExpressionException;

import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import constants.XMLConstants;

import xml.XMLLoader;
import xml.XMLUtils;
import data.DataConstructor;
import data.DataGatherer;
import data.DataGenerator;
import data.DataStorage;
import data.Game;
import data.Player;
import exceptions.DataException;
import exceptions.IdentifierException;

public class XMLGenerator implements DataGenerator{
	private DataConstructor dataGatherer;
	private XMLLoader loader;
	public XMLGenerator() throws ParserConfigurationException, SAXException, IOException{
		this.dataGatherer = new DataGatherer();
		loader = new XMLLoader("C:/Code/balance-ranking/xml/test.xml");
		generateData();
	}
	private static final String XPATH_GAME = XMLConstants.ROOT + XMLConstants.X_SEP + XMLConstants.GAME;
	private static final String XPATH_PLAYERS_IN_GAME = XPATH_GAME +"[%d]" + XMLConstants.X_SEP + XMLConstants.PLAYER;
	private void generateData(){
		try {
			NodeList players = (NodeList) loader.evaluate("data/players/player");
			for (int i = 0; i < players.getLength(); i++) {
				Node player = (Node) players.item(i);
				NamedNodeMap attributes = player.getAttributes();
				String name = attributes.getNamedItem(XMLConstants.NAME).getNodeValue();
				int id = Integer.valueOf(attributes.getNamedItem(XMLConstants.ID).getNodeValue());
				dataGatherer.addPlayer(name,id);
			}
			NodeList games = (NodeList) loader.evaluate(XPATH_GAME);
			for (int i = 0; i < games.getLength(); i++) {
				Node gameNode = (Node) games.item(i);
				Map<String,String> gameAttributes = XMLUtils.getAttributes(gameNode);
				NodeList playersInGame = (NodeList) loader.evaluate(String.format(XPATH_PLAYERS_IN_GAME, i+1));
				//Currently all games must have 2 players.
				Player player1 = getPlayerFromNode(playersInGame.item(0));
				Player player2 = getPlayerFromNode(playersInGame.item(1));
				int player1Score = getPlayerScoreFromNode(playersInGame.item(0));
				int player2Score = getPlayerScoreFromNode(playersInGame.item(1));
				Game game = new Game(player1, player2, player1Score, player2Score, i, gameAttributes.get(XMLConstants.ENVIRONMENT));
				dataGatherer.addGame(game);
			}
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		} catch (IdentifierException e) {
			e.printStackTrace();
		} catch (DataException e) {
			e.printStackTrace();
		}
	}
	private Player getPlayerFromNode(Node player){
		return dataGatherer.getPlayerByID(Integer.valueOf(XMLUtils.getAttributeValue(player, XMLConstants.ID)));
	}
	private int getPlayerScoreFromNode(Node player){
		return Integer.valueOf(XMLUtils.getAttributeValue(player, XMLConstants.SCORE));
	}
	@Override
	public DataStorage getDataStorage() {
		return dataGatherer.getDataStorage();
	}
	
	public static void main(String[] args) {
		try {
			XMLGenerator generator = new XMLGenerator();
			System.out.println(Arrays.toString(generator.getDataStorage().getPlayers()));
			System.out.println(Arrays.toString(generator.getDataStorage().getGames()));
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
